## Warning: package 'knitr' was built under R version 3.6.3
## Warning: package 'rmdformats' was built under R version 3.6.3

1 Veri Çekme ve Yuvarlama Hesaplamaları

R ile zaman serileriyle çalışmaya yönelik bir araç koleksiyonu, veri işlemede herhangi bir tahminci için önemli bir beceridir. timetk paketi, temel veri düzenleme araçlarını içerir. Bu altbölümde göreceklerimiz:

  • Zamana Göre Özetleme - Zamana dayalı toplamalar için

  • Zamana Göre Filtreleme - Karmaşık zamana dayalı filtreleme için

  • Zamana Göre Doldurma - Boşlukları doldurmak ve düşükten yüksek frekansa geçmek için

  • Kaydırma - Herhangi bir işlevi kaydırma (yuvarlanma) işlevine dönüştürmek için

Ek kavramlar:

  • Imputation - Dolgu için Gerekli (Bkz. Düşük - Yüksek Frekans)

  • Gelişmiş Filtreleme - Yeni ekleme süresi% + zaman infix işlemini kullanma (Bkz. Dolgu Verileri: Düşük - Yüksek Frekans)

  • Görselleştirme - tüm görselleştirmeler için plot_time_series()

Gerekli kütüphaneler:

library(tidyverse)
library(tidyquant)
library(timetk)
library(lubridate)
library(modeltime)
library(tidymodels)

1.1 Veri Seti

Burada FANG veri seti kullanılacaktır:

  • Günlük,

  • Düzensiz (tatiller ve haftasonları eksik)

  • 4 grup var (FB, AMZN, NFLX ve GOOG)

glimpse(FANG)
Rows: 4,032
Columns: 8
$ symbol   <chr> "FB", "FB", "FB", "FB", "FB", "FB", "FB", "FB", "FB", "FB"...
$ date     <date> 2013-01-02, 2013-01-03, 2013-01-04, 2013-01-07, 2013-01-0...
$ open     <dbl> 27.44, 27.88, 28.01, 28.69, 29.51, 29.67, 30.60, 31.28, 32...
$ high     <dbl> 28.18, 28.47, 28.93, 29.79, 29.60, 30.60, 31.45, 31.96, 32...
$ low      <dbl> 27.42, 27.59, 27.83, 28.65, 28.86, 29.49, 30.28, 31.10, 30...
$ close    <dbl> 28.00, 27.77, 28.76, 29.42, 29.06, 30.59, 31.30, 31.72, 30...
$ volume   <dbl> 69846400, 63140600, 72715400, 83781800, 45871300, 10478770...
$ adjusted <dbl> 28.00, 27.77, 28.76, 29.42, 29.06, 30.59, 31.30, 31.72, 30...

adjusted sütunu, her bir gün için düzeltilmil kapanış fiyatlarını içerir.

FANG %>% group_by(symbol) %>% plot_time_series(date, adjusted, .facet_ncol = 2, .interactive = FALSE)

Hacim sütunu gün için işlem hacmini (hisse senedinin işlem görme sayısı) içerir.

FANG %>% group_by(symbol) %>% plot_time_series(date, volume, .facet_ncol = 2, .interactive = FALSE)

1.2 Zamana Göre Özetleme

summarise_by_time() periyoda göre toplulaştırma yapar:

  • Periyot toplulaştırma - SUM()

  • Periyot Düzgünleştirme - AVERAGE(), FIRST(), LAST()

1.2.1 Periyot Özetleme

Toplam işlem hacmini çeyrek bazında alalım:

  • SUM() kullanalım

  • .by = "quarter" ile toplulaştıralım.

FANG %>% group_by(symbol) %>% summarise_by_time(date, .by = "quarter", volume = SUM(volume)) %>% 
    plot_time_series(date, volume, .facet_ncol = 2, .interactive = FALSE, .y_intercept = 0)

1.2.2 Periyot Düzgünleştirme

Her aydaki ilk değeri alalım:

  • Verileri azaltma (yani yumuşatma) etkisi olan ilk değeri elde etmek için FIRST() kullanabiliriz. MEAN() veya MEDIAN() kullanabiliriz.

  • Aya göre toplamak için zamana göre özetlemeyi kullanabilriz: .by = "month".

FANG %>% group_by(symbol) %>% summarise_by_time(date, .by = "month", adjusted = FIRST(adjusted)) %>% 
    plot_time_series(date, adjusted, .facet_ncol = 2, .interactive = FALSE)

1.3 Zamana Göre Filtreleme

Düzeltilmiş hisse senedi fiyatlarını 2013’ün 3. çeyreği için filtreleyelim:

  • .start_date = "2013-09": "2013-09-01" e dönüştürülür

  • .end_date = "2013": "2013-12-31" e dönüştürülür

  • %+time ve % -time kullanarak filtrelemenin daha gelişmiş bir örneği “Dolgu Verileri: Düşükten Yüksek Frekansa” gösterilmektedir.

FANG %>% group_by(symbol) %>% filter_by_time(date, "2013-09", "2013") %>% plot_time_series(date, 
    adjusted, .facet_ncol = 2, .interactive = FALSE)

1.4 Veri Doldurma

Boşlukları doldurmak (doldurmak) ve düşük frekanstan yüksek frekansa geçmek için kullanılır. Bu işlev, zaman damgalarını doldurmak ve genişletmek için padr paketini kullanır.

1.4.1 Boşlukları Doldurma

Düzensiz veriyi düzenlileştirelim:

  • Doldurulmuş değerleri NA olarak bırakacağız.

  • .pad_value kullanarak bir değer ekleyebiliriz veya ts_impute_vec () (daha sonra gösterilmektedir) gibi bir işlevi kullanarak doldurabiliriz.

FANG %>% group_by(symbol) %>% pad_by_time(date, .by = "auto")  # Guesses .by = 'day'
# A tibble: 5,836 x 8
# Groups:   symbol [4]
   symbol date        open  high   low close    volume adjusted
   <chr>  <date>     <dbl> <dbl> <dbl> <dbl>     <dbl>    <dbl>
 1 FB     2013-01-02  27.4  28.2  27.4  28    69846400     28  
 2 FB     2013-01-03  27.9  28.5  27.6  27.8  63140600     27.8
 3 FB     2013-01-04  28.0  28.9  27.8  28.8  72715400     28.8
 4 FB     2013-01-05  NA    NA    NA    NA          NA     NA  
 5 FB     2013-01-06  NA    NA    NA    NA          NA     NA  
 6 FB     2013-01-07  28.7  29.8  28.6  29.4  83781800     29.4
 7 FB     2013-01-08  29.5  29.6  28.9  29.1  45871300     29.1
 8 FB     2013-01-09  29.7  30.6  29.5  30.6 104787700     30.6
 9 FB     2013-01-10  30.6  31.5  30.3  31.3  95316400     31.3
10 FB     2013-01-11  31.3  32.0  31.1  31.7  89598000     31.7
# ... with 5,826 more rows

1.4.2 Düşükten Yüksek Frekansa

Başlangıç tarihinden itibaren 1 ay boyunca Günlük zaman damgası aralıklarından Saatlik zaman damgası aralıklarına gidelim. Eksik değerleri uygulaylım.

  • .by = "hour" günlükten saatliğe doldurur.

  • Saatlik verilerin hesaplanması, period = 1 olduğunda doğrusal enterpolasyon yapan ts_impute_vec() ile gerçekleştirilir.

  • Filtreleme, aşağıdakiler kullanılarak gerçekleştirilir:

    • “start”: Bir serinin başlangıcını gösteren özel bir anahtar kelime
    • FIRST(date) %+time% “1 month”: Sıradaki ilk tarihi seçme ve ardından özel bir ek işlemi, %+time%, "add time" adı verilir. Bu durumda “1 month” eklerim.
FANG %>% group_by(symbol) %>% pad_by_time(date, .by = "hour") %>% mutate_at(vars(open:adjusted), 
    .funs = ts_impute_vec, period = 1) %>% filter_by_time(date, "start", FIRST(date) %+time% 
    "1 month") %>% plot_time_series(date, adjusted, .facet_ncol = 2, .interactive = FALSE)

1.5 Kayan (Hareketli) Hesaplamalar

slidify() fonksiyonu, herhangi bir fonksiyonu kayan (yuvarlanan) bir pencere fonksiyonuna dönüştürüyor. tibbletime::rollify() ’den kavramlar alır ve bunları R paketi kaydırıcısı ile geliştirir.

1.5.1 Hareketli Ortalamalar

Kısmi pencere yuvarlanması ve başlangıç ve bitiş pencereleri ile “ortalanmış” basit bir hareketli ortalama hesaplayalım:

  • slidfiy(), AVERAGE() işlevini hareketli ortalamaya dönüştürür.
# Make the rolling function
roll_avg_30 <- slidify(.f = AVERAGE, .period = 30, .align = "center", .partial = TRUE)
# Apply the rolling function
FANG %>% select(symbol, date, adjusted) %>% group_by(symbol) %>% # Apply Sliding Function
mutate(rolling_avg_30 = roll_avg_30(adjusted)) %>% pivot_longer(cols = c(adjusted, 
    rolling_avg_30)) %>% plot_time_series(date, value, .color_var = name, .facet_ncol = 2, 
    .smooth = FALSE, .interactive = FALSE)

Basit hareketli hesaplamalar için (hareketli ortalama), bu işlemi slidify_vec() ile daha hızlı gerçekleştirebiliriz - Basit özet hareketleri için vektörize edilmiş bir yuvarlama işlevi (ör. mean(), sd(), sum(), vb.)

FANG %>% select(symbol, date, adjusted) %>% group_by(symbol) %>% # Apply roll apply Function
mutate(rolling_avg_30 = slidify_vec(adjusted, ~AVERAGE(.), .period = 30, .partial = TRUE))
# A tibble: 4,032 x 4
# Groups:   symbol [4]
   symbol date       adjusted rolling_avg_30
   <chr>  <date>        <dbl>          <dbl>
 1 FB     2013-01-02     28             30.0
 2 FB     2013-01-03     27.8           30.1
 3 FB     2013-01-04     28.8           30.2
 4 FB     2013-01-07     29.4           30.2
 5 FB     2013-01-08     29.1           30.3
 6 FB     2013-01-09     30.6           30.3
 7 FB     2013-01-10     31.3           30.3
 8 FB     2013-01-11     31.7           30.2
 9 FB     2013-01-14     31.0           30.1
10 FB     2013-01-15     30.1           30.1
# ... with 4,022 more rows

1.5.2 Hareketli Regresyon

Hareketli regresyon hesaplayalım:

  • Bu, birden fazla sütunun dahil edilmesini gerektiren karmaşık bir kayan (yuvarlanan) hesaplamadır.

  • slidify() bunun için oluşturulmuştur.

  • Bir işlevi ayarlamak için çok değişkenli purrr ..1, ..2, ..3, vb. gösterimini kullanacağız.

# Rolling regressions are easy to implement using `.unlist = FALSE`
lm_roll <- slidify(~lm(..1 ~ ..2 + ..3), .period = 90, .unlist = FALSE, .align = "right")
FANG %>% select(symbol, date, adjusted, volume) %>% group_by(symbol) %>% mutate(numeric_date = as.numeric(date)) %>% 
    # Apply rolling regression
mutate(rolling_lm = lm_roll(adjusted, volume, numeric_date)) %>% filter(!is.na(rolling_lm))
# A tibble: 3,676 x 6
# Groups:   symbol [4]
   symbol date       adjusted   volume numeric_date rolling_lm
   <chr>  <date>        <dbl>    <dbl>        <dbl> <list>    
 1 FB     2013-05-10     26.7 30847100        15835 <lm>      
 2 FB     2013-05-13     26.8 29068800        15838 <lm>      
 3 FB     2013-05-14     27.1 24930300        15839 <lm>      
 4 FB     2013-05-15     26.6 30299800        15840 <lm>      
 5 FB     2013-05-16     26.1 35499100        15841 <lm>      
 6 FB     2013-05-17     26.2 29462700        15842 <lm>      
 7 FB     2013-05-20     25.8 42402900        15845 <lm>      
 8 FB     2013-05-21     25.7 26261300        15846 <lm>      
 9 FB     2013-05-22     25.2 45314500        15847 <lm>      
10 FB     2013-05-23     25.1 37663100        15848 <lm>      
# ... with 3,666 more rows

2 Zaman Serileri Grafikleri

Bu altbölümde, aşağıdakileri yapan bir zaman serisi çizim işlevi olan plot_time_series() üzerine odaklanılmıştır:

  • Etkileşimli plotly çizimleri (uygulamaları keşfetmek ve parlak hale getirmek için harika)

  • 20’den fazla ggplot2 satırını ve plotly kodunu birleştirir

  • Birçok zaman serisine iyi ölçeklenir

  • Etkileşimli grafikten statik ggplot2 grafiklerine dönüştürülebilir

2.1 Tek Bir Zaman Serisinin Grafiği

30 dakikalık bir örnekleme aralığında megawatt cinsinden enerji talebini içeren popüler bir zaman serisi olan taylor_30_min ile başlayalım. Bu tek bir zaman serisidir.

glimpse(taylor_30_min)
Rows: 4,032
Columns: 2
$ date  <dttm> 2000-06-05 00:00:00, 2000-06-05 00:30:00, 2000-06-05 01:00:0...
$ value <dbl> 22262, 21756, 22247, 22759, 22549, 22313, 22128, 21860, 21751...

plot_time_series() işlevi varsayılan olarak etkileşimli bir grafiksel grafik oluşturur.

  • İlk 2 bağımsız değişken olarak zaman içinde değişen tarih değişkenini (zaman tabanlı sütun, .date_var) ve sayısal değişkeni (.value) sağlamanız yeterlidir.

  • .interactive = TRUE olduğunda, .plotly_slider = TRUE, grafiğin altına bir tarih kaydırıcısı ekler.

taylor_30_min %>% 
  plot_time_series(date, 
                   value, 
                   .interactive = TRUE, # <- Toggle this TRUE/FALSE
                   .plotly_slider = TRUE)

2.2 Zaman Serisi Gruplarının Çizimi

Şimdi, M4 yarışmasından günlük sıklıkta örneklenen 4 zaman serisinin bir örneği olan m4_daily zaman serisi grupları içeren bir veri kümesine geçelim.

Gruplanmış verileri görselleştirmek, veri kümesini plot_time_series() işlevine aktarmadan önce group_by() ile gruplamak kadar basittir. Anahtar noktaları:

  • Gruplar 2 şekilde eklenebilir: group_by() ile veya grup eklemek için kullanılarak.

  • Gruplar daha sonra facet ’a dönüştürülür.

  • .facet_ncol = 2, 2 sütunlu yönlü bir çizim döndürür

  • .facet_scales = "free", her grafiğin x ve y ekseninin diğer grafiklerden bağımsız olarak ölçeklenmesine izin verir

m4_daily %>% group_by(id) %>% plot_time_series(date, value, .facet_ncol = 2, .facet_scales = "free", 
    .interactive = TRUE)

2.3 Düzgünleştirici ile Trend Çizimi

Merak ediyor olabilirsiniz, tüm çizimlerde görünen o mavi çizginin ne olduğunu. Buna daha düzgünleştirici deniyor ve bir zaman serisindeki gürültü aracılığıyla eğilimi görselleştirmenin gerçekten harika bir yoludur.

Düzgünleştiriciyi şu şekilde ayarlayabiliriz:

  • Açma / kapama: .smooth = TRUE/FALSE

  • Satırın esnekliğini değiştirin: .smooth_period = "52 weeks" (30 günlük veriler) veya .smooth_span = 0,25 (verilerin% 25’i) deneyin. Varsayılan olarak, .smooth_span öncelik alır.

m4_weekly %>%
  group_by(id) %>%
  plot_time_series(date, 
                   value, 
                   # Smoother
                   .smooth = TRUE, 
                   .smooth_span = 0.25,           # <- Uses % of data
                   # .smooth_period = "52 weeks", # <- Uses windows of data
                   .facet_ncol = 2, 
                   .facet_scales = "free",
                   .interactive = TRUE)

2.4 Dönüşümleri ve Alt-Grupları Görselleştirme

Birden çok grup içeren saatlik veri kümesine geçelim. Şunları gösterebiliriz:

  • .value’ya günlük dönüşümü

  • Alt grupları vurgulamak için .color_var kullanalım.

Amaç, grupları facet grafiklerde sergilemek, ancak aynı anda değere bir log() dönüşümü yaparken veriler içindeki haftalık pencereleri (haftalık alt gruplar, week() kullanarak) vurgulamaktır. Bunu yapmak çok basit:

  • .value = log(value) Günlük Dönüşümünü uygular

  • Veriler gruplandırılmamıştır, bu nedenle bir veya daha fazla faset sütunu sağlamak için kullanarak dahili olarak facetlar ekleyebiliriz.

  • .color_var = week(date) Tarih sütunu bir lubridate :: week() numarasına dönüştürülür. Renk, hafta numaralarının her birine uygulanır.

m4_hourly %>%
  group_by(id) %>%
  plot_time_series(date, 
                   log(value),             # Apply a Log Transformation
                   .color_var = week(date),      # Color applied to Week transformation
                   # Facet formatting
                   .facet_ncol = 2, 
                   .facet_scales = "free", 
                   .interactive = TRUE)

2.5 Statik ggplot2 Görselleştirmeleri ve Özelleştirme

Tüm görselleştirmeler etkileşimli çizimden (uygulamaları keşfetmek ve parlak uygulamalar için harika) statik ggplot2 görselleştirmelerine (raporlar için harika) dönüştürülebilir.

  • Etkileşimli / Statik arasında geçiş yapılabilir: .interaktif = TRUE / FALSE

  • Başlık, açıklama, x ve y ekseni etiketleri ekleyin: .title, .color_lab, .x_lab ve .y_lab

taylor_30_min %>%
  plot_time_series(date, 
                   value, 
                   .color_var = month(date, label = TRUE),
                   .interactive = FALSE,   # <- Returns static ggplot
                   # Customization
                   .title = "Taylor's MegaWatt Data",
                   .x_lab = "Date (30-min intervals)",
                   .y_lab = "Energy Demand (MW)",
                   .color_lab = "Month") +
  scale_y_continuous(labels = scales::comma_format())

3 Otokorelasyon

Burada aşağıdaki grafikleri etkileşimli bir şekilde sunan plot_acf_diagnostics() işlevine odaklanacağız:

  • ACF ce PACF çizimleri.

  • CCF (Cross Correlation) çizimleri.

Etkileşimli çizimler için plotly, statik çizimler için ggplot2 paketlerini kullanmaktadır.

3.1 Otokorelasyon

Otokorelasyon, bir zaman serisinin gecikmeli değerlerine bağlı korelasyonun varlığıdır. Meslekten olmayan kişilerin terimleriyle bu, geçmiş tarihin gelecekteki tarihle ilgili olduğu anlamına gelir. Bu ilişkiyi bir ACF grafiği ile görselleştirebiliriz.

İlk olarak, plot_time_series() kullanarak taylor_30_min verisine bakacağımız zaman serisini çizelim.

taylor_30_min %>% plot_time_series(date, value, .interactive = T)

Bu seri, yaklaşık 3 ay boyunca 30 dakikalık aralıklarla alınan saatlik elektrik talebini temsil etmektedir. Serideki otokorelasyonu yeni bir fonksiyon olan plot_acf_diagnostics() kullanarak görselleştirebiliriz.

taylor_30_min %>% plot_acf_diagnostics(date, value, .interactive = T)

plot_acf_diagnostics() ’den şunu elde ederiz:

  • ACF Grafiği: Seri ile her aşamalı gecikme (x ekseni) arasındaki ilişkiyi ifade eden otomatik düzeltme (y ekseni).

  • PACF Grafiği: Kısmi otokorelasyon ve gecikmeler. Kısmi Otokorelasyon, her progresif ACF’nin öngörülebilirliğe ne kadar katkıda bulunduğunu gösterir. Başka bir deyişle, birbirleriyle ilişkili gecikmelerin ağırlığı azaltılır, böylece en önemli gecikmeler mevcuttur.

Bu 2 görselleştirme, ilişkileri modellememize ve tahmine dayalı tahminler geliştirmemize yardımcı olur:

  • Mevsimsellik: Bir ilişkiyi modellemek için kullanabileceğimiz Olası Fourier Serileri

  • Tahmin Edici Olarak Gecikmeler: Modellerimize dahil edilecek önemli gecikmeler bulabiliriz.

3.2 Gruplanmış ACF ve PACF Grafikleri

Genellikle zaman serilerinde birden fazla seriyle uğraşırız - bunlara gruplar denir. 4 grup içeren farklı bir saatlik veri kümesine, m4_hourly’ye geçelim.

m4_hourly %>% group_by(id) %>% plot_time_series(date, value, .facet_ncol = 2, .facet_scale = "free", 
    .interactive = T)

ACF ve PACF grafiklerini plot_acf_diagnostics () kullanarak kolayca elde edebiliriz. .lags = "14 days" kullanarak 14 günlük gecikmeleri izole edebiliriz.

m4_hourly %>%
    group_by(id) %>%
    plot_acf_diagnostics(
        date, 
        value,               # ACF & PACF
        .lags = "14 days",         # 14-Days of hourly lags
        .interactive = T
    )

Grupları kullanmak, zaman serilerini her zaman serisini ayrı ayrı analiz etmekten çok daha hızlı değerlendirmemize yardımcı olur. 4 zaman serisini hızlı bir şekilde değerlendirebiliyoruz.

Gruplanmış analiz, zaman serileri arasındaki benzerlikleri ve farklılıkları vurgulayabilir. Günlük sıklığa ek olarak H150 ve H410’da 1 haftada ani artışlar olduğunu görebiliriz.

3.3 Çapraz Korelasyon (Cross Correlation)

Buradaki son örnek, dış yordayıcıları bulmak için önemli bir teknik olan Çapraz Korelasyondur. Walmart için haftalık satışları, çeşitli departmanlardan oluşan zaman serisi gruplarını ve sıcaklık ve yakıt fiyatı dahil olmak üzere birkaç (potansiyel) öngörücüyü içeren yeni bir zaman serisi olan walmart_sales_weekly ile başlıyoruz.

glimpse(walmart_sales_weekly)
Rows: 1,001
Columns: 17
$ id           <fct> 1_1, 1_1, 1_1, 1_1, 1_1, 1_1, 1_1, 1_1, 1_1, 1_1, 1_1,...
$ Store        <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...
$ Dept         <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...
$ Date         <date> 2010-02-05, 2010-02-12, 2010-02-19, 2010-02-26, 2010-...
$ Weekly_Sales <dbl> 24924.50, 46039.49, 41595.55, 19403.54, 21827.90, 2104...
$ IsHoliday    <lgl> FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,...
$ Type         <chr> "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A",...
$ Size         <dbl> 151315, 151315, 151315, 151315, 151315, 151315, 151315...
$ Temperature  <dbl> 42.31, 38.51, 39.93, 46.63, 46.50, 57.79, 54.58, 51.45...
$ Fuel_Price   <dbl> 2.572, 2.548, 2.514, 2.561, 2.625, 2.667, 2.720, 2.732...
$ MarkDown1    <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA...
$ MarkDown2    <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA...
$ MarkDown3    <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA...
$ MarkDown4    <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA...
$ MarkDown5    <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA...
$ CPI          <dbl> 211.0964, 211.2422, 211.2891, 211.3196, 211.3501, 211....
$ Unemployment <dbl> 8.106, 8.106, 8.106, 8.106, 8.106, 8.106, 8.106, 8.106...

Haftalık Satışlar ile Sıcaklık ve Yakıt Fiyatı arasında .ccf_vars kullanarak Çapraz Korelasyonları görselleştirebiliriz.

walmart_sales_weekly %>%
    select(id, Date, Weekly_Sales, Temperature, Fuel_Price) %>%
    group_by(id) %>%
    plot_acf_diagnostics(
        Date, 
        Weekly_Sales,        # ACF & PACF
        .ccf_vars           = c(Temperature, Fuel_Price),   # CCFs
        .show_ccf_vars_only = TRUE,                         # Toggle just CCFs?
        .lags               = "2 years",                    # Lags
        .interactive        = T
    )

4 Mevsimsellik

plot_seasonal_diagnostics (), zaman serisi mevsimselliğini görselleştirmek için etkileşimli ve ölçeklenebilir bir işlevdir.

Aşağıdaki mantığı kullanarak dahil edilecek bir alt özellik yelpazesini tespit etmek için dahili hesaplamalar gerçekleştirilir:

  • Minimum öznitelik, ardışık zaman damgaları arasındaki medyan farkına göre seçilir

  • Maksimum öznitelik, 2 tam döneme göre seçilir.

Örnek: 2 haftadan uzun süren saatlik zaman damgası verileri şu özelliklere sahip olacaktır: "hour", "wday.lbl" ve "week".

Bu işlev, dplyr :: group_by () ile yapılan gruplanmış data.frame ve tibbles’a uyumludur.

Gruplanmış veriler için, döndürülen otomatik özellik seçimi, alt gruplar içindeki tüm özelliklerin bir koleksiyonudur. Bu, bazı gruplar için anlamsız olsalar bile ekstra özelliklerin geri döndüğü anlamına gelir.

.value parametresi dönüşümlere uyar (ör. .value = log (sales))

Mevsimsel çizimler:

taylor_30_min %>% plot_seasonal_diagnostics(date, value, .interactive = T)

Gruplanmış mevsimsel çizimler:

m4_hourly %>% group_by(id) %>% plot_seasonal_diagnostics(date, value, .interactive = T)

4.1 STL Diagnostikleri

plot_stl_diagnostics () işlevi Mevsimsel Eğilim-Düşük ayrışımı (Seasonal-Trend-Loess decomposition) üretir. İşlev, veri çerçeveleri üzerinde çalışması ve dplyr gruplarıyla çalışmak üzere tasarlanması açısından “derli toplu” dur.

STL yöntemi, temel alınan stats :: stl () yöntemini kullanarak zaman serisi ayrıştırmasını uygular. Ayrıştırma, “mevsim” ve “eğilim” bileşenlerini “kalan” bırakarak “gözlemlenen” değerlerden ayırır.

Kullanıcı iki parametreyi kontrol edebilir: .frequency ve .trend.

  • .frequency parametresi, “gözlemlenen” değerlerden kaldırılan “mevsim” bileşenini ayarlar.

  • .trend parametresi, kullanılan trend penceresini (stl () ’den t.window parametresi) ayarlar.

Kullanıcı, zamana dayalı süreler (ör. “6 hafta”) veya sayısal değerler (ör. 180) veya zaman ölçeğine göre sıklığı ve / veya eğilimi otomatik olarak seçen “otomatik” olarak hem .frequency hem de .trend sağlayabilir.

m4_hourly %>% group_by(id) %>% plot_stl_diagnostics(date, value, .frequency = "auto", 
    .trend = "auto", .feature_set = c("observed", "season", "trend", "remainder"), 
    .interactive = T)

5 Anomali Tespiti

Anormallik algılama, zaman serisi analizinin önemli bir parçasıdır:

  • Anormallikleri tespit etmek özel olayları ifade edebilir

  • Anormallikleri temizlemek tahmin hatasını iyileştirebilir

Burada, anormallikleri ölçekte görselleştirmek ve otomatik olarak tespit etmek için plot_anomaly_diagnostics () ve tk_anomaly_diagnostics () işlevlerini ele alacağız.

Veri seti:

glimpse(walmart_sales_weekly)
Rows: 1,001
Columns: 17
$ id           <fct> 1_1, 1_1, 1_1, 1_1, 1_1, 1_1, 1_1, 1_1, 1_1, 1_1, 1_1,...
$ Store        <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...
$ Dept         <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...
$ Date         <date> 2010-02-05, 2010-02-12, 2010-02-19, 2010-02-26, 2010-...
$ Weekly_Sales <dbl> 24924.50, 46039.49, 41595.55, 19403.54, 21827.90, 2104...
$ IsHoliday    <lgl> FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,...
$ Type         <chr> "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A",...
$ Size         <dbl> 151315, 151315, 151315, 151315, 151315, 151315, 151315...
$ Temperature  <dbl> 42.31, 38.51, 39.93, 46.63, 46.50, 57.79, 54.58, 51.45...
$ Fuel_Price   <dbl> 2.572, 2.548, 2.514, 2.561, 2.625, 2.667, 2.720, 2.732...
$ MarkDown1    <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA...
$ MarkDown2    <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA...
$ MarkDown3    <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA...
$ MarkDown4    <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA...
$ MarkDown5    <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA...
$ CPI          <dbl> 211.0964, 211.2422, 211.2891, 211.3196, 211.3501, 211....
$ Unemployment <dbl> 8.106, 8.106, 8.106, 8.106, 8.106, 8.106, 8.106, 8.106...

Anormalliklerle ilgili verileri elde etmek için ön işleme fonksiyonu olan tk_anomaly_diagnostics () kullanıyoruz.

Anormallik tespiti için tk_anomaly_diagnostics () yöntemi, zaman serilerindeki aykırı değerleri tespit etmek için 2 adımlı bir süreç uygular.

  • 1.adım: STL ayrıştırma ile trendden ve mevsimsellikten ayırma.

  • 2.adım: anomli tespiti.

“Trend” ve “mevsim” (mevsimsellik) kaldırıldıktan sonra, “kalan” üzerinde anormallik tespiti yapılır. Anormallikler belirlenir ve sınırlar (recomposed_l1 ve recomposed_l2) belirlenir.

Anormallik Algılama Yöntemi, medyan +/- 25’lik bir iç çeyrek aralığı (IQR) kullanır.

IQR Ayarı, alfa parametresi: Varsayılan alfa = 0,05 ile sınırlar, 25/75 taban çizgisini 3 IQR Faktörü 3 (3X) ile genişleterek belirlenir. IQR Faktörü = 0.15 / alfa (dolayısıyla alfa = 0.05 ile 3X):

  • Sınırları kontrol eden IQR Faktörünü artırmak için alfa’yı azaltın, bu da aykırı değer olmayı zorlaştırır.

  • Aykırı değer olmayı kolaylaştırmak için alfa’yı artırın.

  • IQR aykırı değer algılama yöntemi, tahmini :: tsoutliers () içinde kullanılır.

  • Twitter’ın AnomalyDetection paketi tarafından benzer bir aykırı değer algılama yöntemi kullanılır.

  • Hem Twitter hem de forecast::tsoutliers yöntemleri Business Science’ın anomalize paketinde uygulanmıştır.

walmart_sales_weekly %>% group_by(Store, Dept) %>% tk_anomaly_diagnostics(Date, Weekly_Sales)
# A tibble: 1,001 x 13
# Groups:   Store, Dept [7]
   Store  Dept Date       observed season  trend remainder seasadj remainder_l1
   <dbl> <dbl> <date>        <dbl>  <dbl>  <dbl>     <dbl>   <dbl>        <dbl>
 1     1     1 2010-02-05   24924.   874. 19967.     4083.  24050.      -15981.
 2     1     1 2010-02-12   46039.  -698. 19835.    26902.  46737.      -15981.
 3     1     1 2010-02-19   41596. -1216. 19703.    23108.  42812.      -15981.
 4     1     1 2010-02-26   19404.  -821. 19571.      653.  20224.      -15981.
 5     1     1 2010-03-05   21828.   324. 19439.     2064.  21504.      -15981.
 6     1     1 2010-03-12   21043.   471. 19307.     1265.  20572.      -15981.
 7     1     1 2010-03-19   22137.   920. 19175.     2041.  21217.      -15981.
 8     1     1 2010-03-26   26229.   752. 19069.     6409.  25478.      -15981.
 9     1     1 2010-04-02   57258.   503. 18962.    37794.  56755.      -15981.
10     1     1 2010-04-09   42961.  1132. 18855.    22974.  41829.      -15981.
# ... with 991 more rows, and 4 more variables: remainder_l2 <dbl>,
#   anomaly <chr>, recomposed_l1 <dbl>, recomposed_l2 <dbl>

5.1 Anomalilerin Görselleştirilmesi

walmart_sales_weekly %>% group_by(Store, Dept) %>% plot_anomaly_diagnostics(Date, 
    Weekly_Sales, .facet_ncol = 2)

6 Zaman Serileri Modelleme: modeltime

6.1 1.adım: verinin alınıp eğitim ve test verisi olarak ayrıştırılması

Veri seti:

m750 <- m4_monthly %>% filter(id == "M750")

Görselleştirme:

m750 %>% plot_time_series(date, value, .interactive = T)

Zaman serisini bölme:

# Split Data 80/20
splits <- initial_time_split(m750, prop = 0.9)

6.2 2.adım: birçok model hazırlayıp eğitme

modeltime ve parsnip birleştirerek kolayca düzinelerce tahmin modeli oluşturabiliriz. Ön işleme eklemek için iş akışları arayüzünü de kullanabiliriz! Tahmin olasılıklarınız sonsuzdur. Birkaç temel model geliştirelim:

  • ARIMA

  • Exponential Smoothing

  • Linear Regression

  • MARS (Multivariate Adaptive Regression Splines)

modeltime modelleri (ör. arima_reg()), modelde bir tarih veya tarih saat özelliği ile oluşturulur. Çoğu modelin fit gibi bir formül içerdiğini göreceksiniz (değer ~ tarih, veri).

parsnip modelleri (ör. linear_reg ()) tipik olarak tarih özelliklerine sahip olmamalıdır, ancak tarihlerin türevlerini içerebilir (ör. Ay, yıl vb.). Sıklıklafit (değer ~ sayısal (tarih) + ay (tarih), veri) gibi formüller göreceksiniz.

6.2.1 model 1: auto-arima

# Model 1: auto_arima ----
model_fit_arima_no_boost <- arima_reg() %>% set_engine(engine = "auto_arima") %>% 
    fit(value ~ date, data = training(splits))
# > frequency = 12 observations per 1 year

6.2.2 model 2: boosted auto-arima

# Model 2: arima_boost ----
model_fit_arima_boosted <- arima_boost(min_n = 2, learn_rate = 0.015) %>% set_engine(engine = "auto_arima_xgboost") %>% 
    fit(value ~ date + as.numeric(date) + factor(month(date, label = TRUE), ordered = F), 
        data = training(splits))
# > frequency = 12 observations per 1 year

6.2.3 model 3: exponential smoothing

# Model 3: ets Error-Trend-Season (ETS) ----
model_fit_ets <- exp_smoothing() %>% set_engine(engine = "ets") %>% fit(value ~ date, 
    data = training(splits))
# > frequency = 12 observations per 1 year

6.2.4 model 4: prophet

# Model 4: prophet ----
model_fit_prophet <- prophet_reg() %>% set_engine(engine = "prophet") %>% fit(value ~ 
    date, data = training(splits))
# > Disabling weekly seasonality. Run prophet with weekly.seasonality=TRUE to
# override this. > Disabling daily seasonality. Run prophet with
# daily.seasonality=TRUE to override this.

6.2.5 model 5: lineer regression

# Model 5: lm ----
model_fit_lm <- linear_reg() %>% set_engine("lm") %>% fit(value ~ as.numeric(date) + 
    factor(month(date, label = TRUE), ordered = FALSE), data = training(splits))

6.2.6 model 6: MARS

# Model 6: earth Multivariate Adaptive Regression Spline ----
model_spec_mars <- mars(mode = "regression") %>% set_engine("earth")
recipe_spec <- recipe(value ~ date, data = training(splits)) %>% step_date(date, 
    features = "month", ordinal = FALSE) %>% step_mutate(date_num = as.numeric(date)) %>% 
    step_normalize(date_num) %>% step_rm(date)

wflw_fit_mars <- workflow() %>% add_recipe(recipe_spec) %>% add_model(model_spec_mars) %>% 
    fit(training(splits))

6.3 3.adım: modellerin Model Table’a aktarılması

models_tbl <- modeltime_table(model_fit_arima_no_boost, model_fit_arima_boosted, 
    model_fit_ets, model_fit_prophet, model_fit_lm, wflw_fit_mars)
models_tbl
# Modeltime Table
# A tibble: 6 x 3
  .model_id .model     .model_desc                              
      <int> <list>     <chr>                                    
1         1 <fit[+]>   ARIMA(0,1,1)(0,1,1)[12]                  
2         2 <fit[+]>   ARIMA(0,1,1)(0,1,1)[12] W/ XGBOOST ERRORS
3         3 <fit[+]>   ETS(M,A,A)                               
4         4 <fit[+]>   PROPHET                                  
5         5 <fit[+]>   LM                                       
6         6 <workflow> EARTH                                    

6.4 4.adım: test verisine karşı model kalibrasyonu

calibration_tbl <- models_tbl %>% modeltime_calibrate(new_data = testing(splits))

calibration_tbl
# Modeltime Table
# A tibble: 6 x 5
  .model_id .model     .model_desc                        .type .calibration_da~
      <int> <list>     <chr>                              <chr> <list>          
1         1 <fit[+]>   ARIMA(0,1,1)(0,1,1)[12]            Test  <tibble [31 x 4~
2         2 <fit[+]>   ARIMA(0,1,1)(0,1,1)[12] W/ XGBOOS~ Test  <tibble [31 x 4~
3         3 <fit[+]>   ETS(M,A,A)                         Test  <tibble [31 x 4~
4         4 <fit[+]>   PROPHET                            Test  <tibble [31 x 4~
5         5 <fit[+]>   LM                                 Test  <tibble [31 x 4~
6         6 <workflow> EARTH                              Test  <tibble [31 x 4~

6.5 5.adım: test verisi tahmini ve doğruluğu geliştirme

Test Hatasını görselleştirmek, etkileşimli grafiksel görselleştirmeyi kullanarak yapmak kolaydır (Legend kullanarak modellerin görünürlüğünü değiştirebiliriz).

calibration_tbl %>%
    modeltime_forecast(
        new_data    = testing(splits),
        actual_data = m750
    ) %>%
    plot_modeltime_forecast(
      .legend_max_width = 25, # For mobile screens
      .interactive      = T
    )

Test seti tahminini görselleştirmekten:

  • Model 1 ve 2: ARIMA & ARIMA Boost iyi performans gösteriyor. Auto ARIMA kullandığımız için her iki modelde de “otomatik” bileşenler var. XGBoost bileşeni, belirtilen parametrelere sahiptir. Ayarlayarak daha iyi bir doğruluk elde edebiliriz, ancak ARIMA bileşeni bu veriler üzerinde iyi çalıştığı için ek iyileştirme düşük olabilir.

  • Model 3: ETS (M, A, A) en iyi performansı gösteriyor. % 80 güven aralığı, grubun en dar olanıdır ve bu, bekleme setinin iyi modellendiğini gösterir.

  • Model 4: PROPHET, ARIMA modelleriyle karşılaştırılabilir, ancak biraz daha geniş bir test hatası güven aralığına sahiptir.

  • Model 5: LM, yerel trendi abartıyor. Bunun nedeni, eğilim bileşeninin değişim noktalarını hesaba katmayan basit bir doğrusal çizgi olmasıdır.

  • Model 6: EARTH yerel eğilime fazla uyuyor. Bunun nedeni, değişim noktalarının sayısını ayarlamadığımız için, algoritmanın değişim noktalarını otomatik olarak hesaplamasıdır.

Doğruluk metrikleri:

  • MAE - Mean absolute error, mae()

  • MAPE - Mean absolute percentage error, mape()

  • MASE - Mean absolute scaled error, mase()

  • SMAPE - Symmetric mean absolute percentage error, smape()

  • RMSE - Root mean squared error, rmse()

  • RSQ - R-squared, rsq()

calibration_tbl %>% modeltime_accuracy() %>% table_modeltime_accuracy(.interactive = T)

Doğruluk ölçümlerinden:

  • Model 3: ETS, 77 MAE ile burada açıkça kazanan modeldir.

  • Model 6: MARS, yerel trendi aşıyor. Bu, 0.55’in R-Karesinde çıkar.

6.6 6.adım: tüm veri için yeniden eğitilip gelecek tahminlerinin türetilmesi

refit_tbl <- calibration_tbl %>%
    modeltime_refit(data = m750)
refit_tbl %>%
    modeltime_forecast(h = "3 years", actual_data = m750) %>%
    plot_modeltime_forecast(
      .legend_max_width = 25, # For mobile screens
      .interactive      = T
    )

Modellerin hepsi değişti! (Evet - bu yeniden eğitme için kritik noktadır)

  • LM modeli şimdi çok daha iyi görünüyor çünkü doğrusal eğilim çizgisi artık daha uzun vadeli eğilimi izleyen yeni verilere uyuyor.

  • EARTH modeli, kısa vadeli eğilimi daha çok temsil eden bir eğilime sahiptir.

  • PROPHET modelinin EARTH modeline çok benzer bir eğilimi vardır (bunun nedeni, her iki modelleme algoritmasının eğilimi modellemek için değişim noktaları kullanması ve peygamberin otomatik algoritmasının uyum sağlamada daha iyi bir iş çıkarmasıdır).

  • ETS modeli (M, A, A) yerine (A, A, A) olarak değiştirildi.

  • ARIMA modeli güncellendi ve yükselişi daha iyi yakaladı.

Bu, yeniden eğitmenin (potansiyel) faydasıdır.

Çoğu zaman yeniden eğitmemek iyi bir fikirdir. Yeniden eğitme:

  • Modelinizi ve ön işleme adımlarınızı alır

  • Modeli yeni verilere yeniler

  • Herhangi bir otomasyonu yeniden hesaplar. Bu şunları içerir:

    • Doğrusal Model için uzun vadeli eğilimi yeniden hesaplamak
    • Dünya Modeli için değişim noktalarını yeniden hesaplama
    • ARIMA ve ETS parametrelerini yeniden hesaplama
  • Tüm parametre seçimlerini korur. Bu şunları içerir:

    • Boosted ARIMA min_n = 2’deki XGBoost Parametreleri, learn_rate = 0.015.
    • Otomatik hesaplamalar olmayan diğer varsayılanlar kullanılır.